spring cloud gateway 动态路由配置 动态路由的谓词设置 动态路由的谓词 predicates,主要分为以下几个类别:
Path 路由匹配,请求path的匹配,动态配置的参数方式如下,构建PredicateDefinition
对应参数的key值为pattern
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"Path" , "args" :{ "pattern" :"/demo-service/**" } } ] }
对应源码如下
1 2 3 4 5 6 7 8 9 10 11 12 return (exchange) -> { PathContainer path = PathContainer.parsePath(exchange.getRequest().getURI().getPath()); boolean match = config.pathPattern.matches(path); traceMatch("Pattern" , config.pathPattern.getPatternString(), path, match); if (match) { PathMatchInfo uriTemplateVariables = config.pathPattern.matchAndExtract(path); exchange.getAttributes().put(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); return true ; } else { return false ; } };
Before 路由匹配:当时间在before配置的时间(zoneTime)之前生效
对应的参数:datetime
动态配置如下:
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"Before" , "args" :{ "datetime" :"2018-12-12T11:14:03.820+08:00[Asia/Shanghai]" } } ] }
对应源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static final String DATETIME_KEY = "datetime" ;public BeforeRoutePredicateFactory () { super (BeforeRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder () { return Collections.singletonList("datetime" ); } public Predicate<ServerWebExchange> apply (BeforeRoutePredicateFactory.Config config) { ZonedDateTime datetime = BetweenRoutePredicateFactory.getZonedDateTime(config.getDatetime()); return (exchange) -> { ZonedDateTime now = ZonedDateTime.now(); return now.isBefore(datetime); }; }
After 路由匹配:当时间在After配置的时间(zoneTime)之后生效
对应参数: datetime
动态路由配置:
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"After" , "args" :{ "datetime" :"2018-12-12T11:14:03.820+08:00[Asia/Shanghai]" } } ] }
对应源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static final String DATETIME_KEY = "datetime" ; public AfterRoutePredicateFactory () { super (AfterRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder () { return Collections.singletonList("datetime" ); } public Predicate<ServerWebExchange> apply (AfterRoutePredicateFactory.Config config) { ZonedDateTime datetime = BetweenRoutePredicateFactory.getZonedDateTime(config.getDatetime()); return (exchange) -> { ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(datetime); }; }
Between 路由匹配:当时间在between设置的两个时间点之间,则匹配。
对应参数 datetime1
datetime2
Datetime1 对应的起始时间
Datetime2 对应的结束时间
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "predicates" :[ { "name" :"Between" , "args" :{ "datetime1" :"2018-12-12T11:14:03.820+08:00[Asia/Shanghai]" , "datetime2" :"2018-12-12T15:14:03.820+08:00[Asia/Shanghai]" } } ] }
对应源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static final String DATETIME1_KEY = "datetime1" ; public static final String DATETIME2_KEY = "datetime2" ; public BetweenRoutePredicateFactory () { super (BetweenRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder () { return Arrays.asList(new String[]{"datetime1" , "datetime2" }); } public Predicate<ServerWebExchange> apply (BetweenRoutePredicateFactory.Config config) { ZonedDateTime datetime1 = getZonedDateTime(config.datetime1); ZonedDateTime datetime2 = getZonedDateTime(config.datetime2); Assert.isTrue(datetime1.isBefore(datetime2), config.datetime1 + " must be before " + config.datetime2); return (exchange) -> { ZonedDateTime now = ZonedDateTime.now(); return now.isAfter(datetime1) && now.isBefore(datetime2); }; }
路由匹配:在http请求头中包含对应的key和value,则匹配
对应参数:header
regexp
header 在Header中设置的key值
regexp key对应的value,支持正则表达式
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "predicates" :[ { "name" :"Header" , "args" :{ "header" :"version" , "regexp" :"V1.0" } } ] }
对应源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static final String HEADER_KEY = "header"; public static final String REGEXP_KEY = "regexp"; public HeaderRoutePredicateFactory() { super(HeaderRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder() { return Arrays.asList(new String[]{"header", "regexp"}); } public Predicate<ServerWebExchange> apply(HeaderRoutePredicateFactory.Config config) { return (exchange) -> { List<String> values = exchange.getRequest().getHeaders().get(config.header); if(values != null) { Iterator var3 = values.iterator(); while(var3.hasNext()) { String value = (String)var3.next(); if(value.matches(config.regexp)) { return true; } } } return false; }; }
Host 路由匹配:在http请求头中包含对应的Host信息,则匹配
对应参数 pattern
pattern 对应host的正则表达式
动态配置
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"Host" , "args" :{ "pattern" :"10.88.**" } } ] }
对应源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private PathMatcher pathMatcher = new AntPathMatcher("."); public HostRoutePredicateFactory() { super(HostRoutePredicateFactory.Config.class); } public void setPathMatcher(PathMatcher pathMatcher) { this.pathMatcher = pathMatcher; } public List<String> shortcutFieldOrder() { return Collections.singletonList("pattern"); } public Predicate<ServerWebExchange> apply(HostRoutePredicateFactory.Config config) { return (exchange) -> { String host = exchange.getRequest().getHeaders().getFirst("Host"); return this.pathMatcher.match(config.getPattern(), host); }; }
Method 路由匹配:当请求的Method与配置的method一致,则匹配
对应参数:method
method就是http标准的method内容如GET POST DELETE等
动态配置:
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"Method" , "args" :{ "method" :"GET" } } ] }
对应源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static final String METHOD_KEY = "method"; public MethodRoutePredicateFactory() { super(MethodRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder() { return Arrays.asList(new String[]{"method"}); } public Predicate<ServerWebExchange> apply(MethodRoutePredicateFactory.Config config) { return (exchange) -> { HttpMethod requestMethod = exchange.getRequest().getMethod(); return requestMethod == config.getMethod(); }; }
Cookie 路由匹配:当请求的cookie中包含有对应的key和value,则匹配
对应参数:name
regexp
name cookie中对应的key值
regexp 与cookie的key对应的value,支持正则表达式
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "predicates" :[ { "name" :"Cookie" , "args" :{ "name" :"patrick" , "regexp" : "123" } } ] }
相关源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public static final String NAME_KEY = "name" ; public static final String REGEXP_KEY = "regexp" ; public CookieRoutePredicateFactory () { super (CookieRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder () { return Arrays.asList(new String[]{"name" , "regexp" }); } public Predicate<ServerWebExchange> apply (CookieRoutePredicateFactory.Config config) { return (exchange) -> { List<HttpCookie> cookies = (List)exchange.getRequest().getCookies().get(config.name); if (cookies == null ) { return false ; } else { Iterator var3 = cookies.iterator(); HttpCookie cookie; do { if (!var3.hasNext()) { return false ; } cookie = (HttpCookie)var3.next(); } while (!cookie.getValue().matches(config.regexp)); return true ; } }; }
Query 路由匹配:当请求的url对应的parameter的key value与设置的一一对应,则匹配
参数: param
regexp
Param url参数的key值
regexp url的key对应的value值,可以为正则表达式
当时配置多个Query的时候,是&运算,如果key不一致,gateway会提示500错,如果value不一致,则提示404错误
动态配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "predicates" :[ { "name" :"Query" , "args" :{ "param" :"patrick" , "regexp" : "123" } }, { "name" :"Query" , "args" :{ "param" :"haha" , "regexp" : "hehe" } } ] }
相关源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public static final String PARAM_KEY = "param" ; public static final String REGEXP_KEY = "regexp" ; public QueryRoutePredicateFactory () { super (QueryRoutePredicateFactory.Config.class); } public List<String> shortcutFieldOrder () { return Arrays.asList(new String[]{"param" , "regexp" }); } public Predicate<ServerWebExchange> apply (QueryRoutePredicateFactory.Config config) { return (exchange) -> { if (!StringUtils.hasText(config.regexp)) { return exchange.getRequest().getQueryParams().containsKey(config.param); } else { List<String> values = (List)exchange.getRequest().getQueryParams().get(config.param); Iterator var3 = values.iterator(); String value; do { if (!var3.hasNext()) { return false ; } value = (String)var3.next(); } while (!value.matches(config.regexp)); return true ; } }; }
RemoteAddr 路由匹配:当客户端的ip与设置的ip段一致,则匹配
参数 sources
sources 配置客户端的ip地址段 如192.168.1.1/24
动态配置:
1 2 3 4 5 6 7 8 9 10 { "predicates" :[ { "name" :"RemoteAddr" , "args" :{ "sources" :"192.168.1.1/24" } } ] }
对应源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public Predicate<ServerWebExchange> apply (RemoteAddrRoutePredicateFactory.Config config) { List<IpSubnetFilterRule> sources = this .convert(config.sources); return (exchange) -> { InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange); if (remoteAddress != null ) { String hostAddress = remoteAddress.getAddress().getHostAddress(); String host = exchange.getRequest().getURI().getHost(); if (log.isDebugEnabled() && !hostAddress.equals(host)) { log.debug("Remote addresses didn't match " + hostAddress + " != " + host); } Iterator var6 = sources.iterator(); while (var6.hasNext()) { IpSubnetFilterRule source = (IpSubnetFilterRule)var6.next(); if (source.matches(remoteAddress)) { return true ; } } } return false ; }; }
动态路由gatewayFilter设置 过滤器功能:网关为请求的header添加key value
参数 name
value
name 添加header的key
value 添加header对应key的value
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "filters" :[ { "name" :"AddRequestHeader" , "args" :{ "name" :"patrick" , "value" :"bar" } } ] }
过滤器功能:网关为请求的header抹去key value
参数 name
name 需要抹去的header中的key
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"RemoveRequestHeader" , "args" :{ "name" :"patrick" } } ] }
过滤器功能:网关将返回的header的头remove对应的key
参数:name
name 需要抹去的header的key
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"RemoveResponseHeader" , "args" :{ "name" :"patrick" } } ] }
过滤器功能:网关添加ResponseHeader的key和value
参数:name
value
name 需要添加在response header的key
value 需要添加在response header的key对应的value
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"AddResponseHeader" , "args" :{ "name" :"patrick" } } ] }
过滤器功能:网关设置ResponseHeader的key和value
参数 name
value
name 需要设置在response header的key
value 需要设置在response header的key对应的value
与addResponseHeader的区别,应用官网的原话
This GatewayFilter replaces all headers with the given name, rather than adding. So if the downstream server responded with a X-Response-Foo:1234
, this would be replaced with X-Response-Foo:Bar
, which is what the gateway client would receive.
重置指定的key value
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"SetResponseHeader" , "args" :{ "name" :"patrick" } } ] }
AddRequestParameter 过滤器功能:网关给请求的url中添加param
参数: name
value
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "filters" :[ { "name" :"AddRequestParameter" , "args" :{ "name" :"patrick" , "value" : "test" } } ] }
RewritePath 过滤器功能:应用请求通过predicate匹配到对应的route后,需要将url进行替换,发送到指定的后端模块
参数: regexp
replacement
regexp 需要替换的path的正则表达式
replacement 替换的内容的正则
动态配置:
1 2 3 4 5 6 7 { "name" :"RewritePath" , "args" :{ "regexp" :"/demo-service/(?<remaining>.*)" , "replacement" :"/${remaining}" } }
PrefixPath 过滤器功能:请求到具体服务的path时,给path前面加上前缀 prefix
参数:prefix
prefix 给路由目标路径前添加前缀
This will prefix /mypath
to the path of all matching requests. So a request to /hello
, would be sent to /mypath/hello
.
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"PrefixPath" , "args" :{ "prefix" :"/mypath" } } ] }
SetPath 过滤器功能:请求到具体服务的path时,通过template对应的内容对整个uri进行替换
参数:template
template 需要替换掉uri的内容模版
For a request path of /foo/bar
, this will set the path to /bar
before making the downstream request.
动态配置:
1 2 3 4 5 6 7 8 9 10 { "filters" :[ { "name" :"SetPath" , "args" :{ "template" :"/mypath" } } ] }
RedirectTo 过滤器功能:设置跳转到三方系统,http的状态码必须为3xx系列。
参数:status
url
status 跳转的http状态码,必须是3xx,比如302
url 跳转的地址
动态配置:
1 2 3 4 5 6 7 8 9 10 11 { "filters" :[ { "name" :"RedirectTo" , "args" :{ "status" : 302 , "url" : "http://www.baidu.com" } } ] }